define([
    "moment", "pako", "jquery", "jquery.json", "base64js"
], function(moment, pako) {

    /**
     * SzTime, declaration.
     */
    var SzLib = function() {};

    /**
     * Get the timestamp of now.
     *
     * @return {Number} timestamp
     */
    SzLib.getTime = function() {
        return moment().format('X');
    };

    /**
     * Get time string of 'YYYY-mm-dd HH:ii:ss' of now.
     *
     * @return {String} time
     */
    SzLib.setTime = function() {
        return moment().format('YYYY-MM-DD HH:mm:ss');
    };

    /**
     * Get swf movie on page.
     *
     * @return {Object} swfMovie
     */
    SzLib.getMovie = function(movieName) {
        if (navigator.userAgent.indexOf('MSIE') != -1) { // IE 6 - IE 10
            return window[movieName];
        } else if (Object.hasOwnProperty.call(window, "ActiveXObject") && !window.ActiveXObject) { // IE 11
            return window[movieName];
        } else {
            return document[movieName];
        }
    };

    /**
     * Format object to json string with '<pre>' tags wrapped.
     *
     * @param {Object} object
     * @return {String} msg
     */
    SzLib.printObject = function(object) {
        var msg = '';
        if (typeof JSON != 'undefined') {
            msg = JSON.stringify(object, null, "\t");
        } else {
            msg = $.toJSON(object);
        }

        return '<pre>' + msg + '</pre>';
    };

    /**
     * Get url param.
     *
     * @param {String} name the name of the param
     * @return {String} param
     */
    SzLib.getUrlParam = function(name) {
        var reg = new RegExp("(^|&)"+ name +"=([^&]*)(&|$)");
        var r = window.location.search.substr(1).match(reg);
        if (r!==null) return unescape(r[2]); return null;
    };

    /**
     * Refresh page.
     *
     * @return {void}
     */
    SzLib.refreshPage = function() {
        window.location.reload();
    };

    /**
     * Log message.
     *
     * @param {String|Object} msg
     * @return {void}
     */
    SzLib.log = function(msg) {
        if (typeof console === 'object') {
            if (typeof msg == 'string') {
                console.log('[' + SzLib.setTime() + '] ' + msg);
            } else {
                console.log('[' + SzLib.setTime() + ']: ', msg);
            }
        }
    };

    /**
     * Convert the first character of the given string to upper case.
     *
     * @param {String} str
     * @return {String}
     */
    SzLib.ucfirst = function(str) {
        return str.charAt(0).toUpperCase() + str.slice(1);
    };

    /**
     * Uint8 array to string
     *
     * @param {Uint8Array} ua
     * @return {String}
     */
    SzLib.byteArrayToString = function(ua) {
        var s = '';
        for (var i = 0; i < ua.length; i++) {
            s += String.fromCharCode(ua[i]);
        }
        return s;
    };

    /**
     * Use gzcompress to compress string data, encoding ZLIB_ENCODING_DEFLATE.
     *
     * @param {Object} object
     * @param {Boolean} needBase64Encode
     * @return {Object}
     */
    SzLib.compress = function(object, needBase64Encode) {
        var deflated = pako.deflate($.toJSON(object));

        if (needBase64Encode) {
            deflated = base64js.fromByteArray(deflated);
        }

        return deflated;
    };

    /**
     * Use gzuncompress to decompress string data, encoding ZLIB_ENCODING_DEFLATE.
     *
     * @param {String | Object} data
     * @param {Boolean} needBase64Decode
     * @return {Object}
     */
    SzLib.decompress = function(data, needBase64Decode) {
        if (needBase64Decode) {
            data = base64js.toByteArray(data);
        }
        var inflated = pako.inflate(data);
        return $.parseJSON(SzLib.byteArrayToString(inflated));
    };

    /**
     * Send async POST request.
     *
     * @param {Object} params
     * @param {Function} onSuccess
     * @param {Function} onFailure
     * @param {String} url
     * @param {String} dataType
     * @param {Boolean} isCompress
     * @return {void}
     */
    SzLib.sendReq = function(params, onSuccess, onFailure, url, dataType, isCompress) {
        if (typeof params != 'object' || typeof onSuccess != 'function') {
            return;
        }
        if (isCompress) {
            dataType = 'text';
        }

        $.ajax({
            type: 'POST',
            url: (typeof url === 'string' && url !== null && url !== '') ? url : SZ.REQUEST_URL,
            data: params,
            dataType: (typeof dataType === 'string' && dataType !== null && dataType !== '') ? dataType : 'json',
            success: function(data) {
                if (null === data) {
                    // no response, display error message
                    if (typeof onFailure == 'function') {
                        onFailure();
                    }
                    SzLib.log('Request failed! null data returned!');
                } else {
                    // means this is a successful response, call response function
                    onSuccess(data);
                    SzLib.log('Request succeed! response function called!');
                }
            },
            error: function(err){
                if (typeof onFailure == 'function') {
                    onFailure(err);
                }
                SzLib.log('Request failed! Error message: ' + err.responseText);
            }
        });
    };

    /**
     * Send async POST request. Follow the message format of SzFramework.
     *
     * @param {Object} params
     * @param {Function} onSuccess
     * @param {Function} onFailure
     * @param {Object} addParams
     * @param {Boolean} isCompress
     * @return {void}
     */
    SzLib.sendSzReq = function(params, onSuccess, onFailure, addParams, isCompress) {
        if (typeof params !== 'object' || typeof onSuccess !== 'function') {
            return;
        }

        var dataType;
        var data;
        if (isCompress) {
            dataType = 'text';
            data = {"*": SzLib.compress([params], true)};
        } else {
            dataType = 'json';
            data = {"*": [params]};
        }

        if (typeof addParams === 'object') {
            $.extend(data, addParams);
        }
        $.ajax({
            type: 'POST',
            url: SZ.REQUEST_URL,
            data: data,
            dataType: dataType,
            success: function(data) {
                if (isCompress) {
                    data = SzLib.decompress(data, true);
                }
                if (null === data) {
                    // no response, display error message
                    if (typeof onFailure === 'function') {
                        onFailure();
                    }
                    SzLib.log('Request failed! null data returned!');
                } else if (null !== data && 'object' === typeof data && data.code !== 0) {
                    // means this is an error reponse
                    // 'code' means response result status, 0 means succeed, otherwise it means error code
                    if (typeof onFailure === 'function') {
                        onFailure(data);
                    }
                    SzLib.log('Request failed! Err code: ' + data.code + ', Err msg: ' + data.msg);
                } else {
                    // means this is a successful response, call response function
                    onSuccess(data.msg[0]);
                    SzLib.log('Request succeed! response function called!');
                }
            },
            error: function(err){
                if (typeof onFailure === 'function') {
                    onFailure(err);
                }
                SzLib.log('Request failed! Error message: ' + err.responseText);
            }
        });
    };

    /**
     * Get http resource.
     *
     * @param {String} url
     * @param {Function} onSuccess
     * @return {void}
     */
    SzLib.getResource = function(url, onSuccess) {
        $.get(url, function(data) {
            onSuccess(data);
        });
    };

    /**
     * String replace via argus
     */
    SzLib.strReplace = function(str, argus) {
        if (argus.length === 0) {
            return str;
        }
        for (var i = 0; i < argus.length; i++) {
            str = str.replace(/%s/, argus[i]);
        }
        return str;
    };

    /**
     * Get window protocol
     */
    SzLib.getWindowProtocol = function() {
        return window.location.protocol;
    };

    /**
     * Base64, declaration.
     */
    SzLib.Base64 = {
        // private property
        _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",

        // public method for encoding
        encode : function(input) {
            var output = "";
            var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
            var i = 0;

            input = SzLib.Base64._utf8_encode(input);

            while (i < input.length) {

                chr1 = input.charCodeAt(i++);
                chr2 = input.charCodeAt(i++);
                chr3 = input.charCodeAt(i++);

                enc1 = chr1 >> 2;
                enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
                enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
                enc4 = chr3 & 63;

                if (isNaN(chr2)) {
                    enc3 = enc4 = 64;
                } else if (isNaN(chr3)) {
                    enc4 = 64;
                }

                output = output + SzLib.Base64._keyStr.charAt(enc1)
                    + SzLib.Base64._keyStr.charAt(enc2)
                    + SzLib.Base64._keyStr.charAt(enc3)
                    + SzLib.Base64._keyStr.charAt(enc4);

            }

            return output;
        },

        // public method for decoding
        decode : function(input) {
            var output = "";
            var chr1, chr2, chr3;
            var enc1, enc2, enc3, enc4;
            var i = 0;

            input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

            while (i < input.length) {

                enc1 = SzLib.Base64._keyStr.indexOf(input.charAt(i++));
                enc2 = SzLib.Base64._keyStr.indexOf(input.charAt(i++));
                enc3 = SzLib.Base64._keyStr.indexOf(input.charAt(i++));
                enc4 = SzLib.Base64._keyStr.indexOf(input.charAt(i++));

                chr1 = (enc1 << 2) | (enc2 >> 4);
                chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
                chr3 = ((enc3 & 3) << 6) | enc4;

                output = output + String.fromCharCode(chr1);

                if (enc3 != 64) {
                    output = output + String.fromCharCode(chr2);
                }
                if (enc4 != 64) {
                    output = output + String.fromCharCode(chr3);
                }

            }

            output = SzBase64._utf8_decode(output);

            return output;

        },

        // private method for UTF-8 encoding
        _utf8_encode : function(string) {
            string = string.replace(/\r\n/g, "\n");
            var utftext = "";

            for ( var n = 0; n < string.length; n++) {

                var c = string.charCodeAt(n);

                if (c < 128) {
                    utftext += String.fromCharCode(c);
                } else if ((c > 127) && (c < 2048)) {
                    utftext += String.fromCharCode((c >> 6) | 192);
                    utftext += String.fromCharCode((c & 63) | 128);
                } else {
                    utftext += String.fromCharCode((c >> 12) | 224);
                    utftext += String.fromCharCode(((c >> 6) & 63) | 128);
                    utftext += String.fromCharCode((c & 63) | 128);
                }

            }

            return utftext;
        },

        // private method for UTF-8 decoding
        _utf8_decode : function(utftext) {
            var string = "";
            var i = 0;
            var c = 0, c1 = 0, c2 = 0;

            while (i < utftext.length) {

                c = utftext.charCodeAt(i);

                if (c < 128) {
                    string += String.fromCharCode(c);
                    i++;
                } else if ((c > 191) && (c < 224)) {
                    c1 = utftext.charCodeAt(i + 1);
                    string += String.fromCharCode(((c & 31) << 6)
                        | (c1 & 63));
                    i += 2;
                } else {
                    c1 = utftext.charCodeAt(i + 1);
                    c2 = utftext.charCodeAt(i + 2);
                    string += String.fromCharCode(((c & 15) << 12)
                        | ((c1 & 63) << 6) | (c2 & 63));
                    i += 3;
                }

            }
            return string;
        }
    };

    /**
     * valid chinese IdentityCode
     *
     * @param idCode
     * @returns {string}
     */
    SzLib.validIdentityCode = function (code) {
        var city={11:"北京",12:"天津",13:"河北",14:"山西",15:"内蒙古",21:"辽宁",22:"吉林",23:"黑龙江 ",31:"上海",32:"江苏",33:"浙江",34:"安徽",35:"福建",36:"江西",37:"山东",41:"河南",42:"湖北 ",43:"湖南",44:"广东",45:"广西",46:"海南",50:"重庆",51:"四川",52:"贵州",53:"云南",54:"西藏 ",61:"陕西",62:"甘肃",63:"青海",64:"宁夏",65:"新疆",71:"台湾",81:"香港",82:"澳门",91:"国外 "};
        var tip = "";
        var pass= true;

        if(!code || !/^\d{6}(18|19|20)?\d{2}(0[1-9]|1[12])(0[1-9]|[12]\d|3[01])\d{3}(\d|X)$/i.test(code)){
            tip = "身份证号格式错误";
            pass = false;
        }

        else if(!city[code.substr(0,2)]){
            tip = "身份证号格式错误，地址编码错误";
            pass = false;
        }
        else{
            //18位身份证需要验证最后一位校验位
            if(code.length == 18){
                code = code.split('');
                //∑(ai×Wi)(mod 11)
                //加权因子
                var factor = [ 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 ];
                //校验位
                var parity = [ 1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2 ];
                var sum = 0;
                var ai = 0;
                var wi = 0;
                for (var i = 0; i < 17; i++)
                {
                    ai = code[i];
                    wi = factor[i];
                    sum += ai * wi;
                }
                var last = parity[sum % 11];
                if(parity[sum % 11] != code[17]){
                    tip = "校验位错误";
                    pass =false;
                }
            }
        }


        if(!pass) {
            //alert(tip);
        } else {
            //alert('pass');
            tip = "pass";
        }
        return tip;
    };

    return SzLib;

});